using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

// Farseer Physics Library.
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Factories;
using FarseerGames.FarseerPhysics.Controllers;
using FarseerGames.FarseerPhysics.Interfaces;

namespace GameLib
{
    // The map class contains data for drawing a level.
    // The map class contains data for drawing a level.
    public class Map
    {
        public string Name;
        public Vector2 Size;
        public Vector2 TileSize;
        public string TextureType;

        public int[] BackgroundLayer;
        public int[] BaseLayer;
        public int[] ForegroundLayer;

        private Tile[] Tiles;

        private ContentManager Content;

        #region Load the layers

        public void Load(ref Game game, ref PhysicsSimulator physicsSimulator)
        {
            Content = game.Content;
            
            Tiles = new Tile[(int)(Size.X * Size.Y)];
            
            // Fill the tile array with the values from the baselayer.
            for (int t = 0; t < Tiles.Length; t++)
            {
                Tiles[t] = LoadTile(ref game, BaseLayer[t]);
            }

            LoadBaseLayer(ref physicsSimulator);
        }

        private void LoadBackgroundLayer(ref PhysicsSimulator physicsSimulator)
        {

        }

        private void LoadBaseLayer(ref PhysicsSimulator physicsSimulator)
        {
            int currentTile = 0;
            for (int row = 0; row < Size.Y; row++)
            {
                for (int col = 0; col < Size.X; col++)
                {
                    if (Tiles[currentTile].Collision == TileCollision.Impassable)
                    {
                        Tiles[currentTile].Body = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, TileSize.X, TileSize.Y, 1);

                        Tiles[currentTile].Body.Position = new Vector2(col * TileSize.X, row * TileSize.Y);
                        Tiles[currentTile].Body.IsStatic = true;
                        Tiles[currentTile].Geom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, Tiles[currentTile].Body, TileSize.X, TileSize.Y);
                    }
                    currentTile++;
                }
            }
        }

        private void LoadForegroundLayer()
        {

        }

        #endregion

        #region Draw the layers.

        public void Draw(ref SpriteBatch spriteBatch)
        {
            DrawBaseLayer(ref spriteBatch);
        }

        private void DrawBackgroundLayer(ref SpriteBatch spriteBatch)
        {

        }

        private void DrawBaseLayer(ref SpriteBatch spriteBatch)
        {
            int currentTile = 0;
            for (int row = 0; row < Size.Y; row++)
            {
                for (int col = 0; col < Size.X; col++)
                {
                    if (Tiles[currentTile].Body != null)
                    {
                        // Draw it in screen space.                        
                        spriteBatch.Draw(Tiles[currentTile].Texture, new Vector2(Tiles[currentTile].Body.Position.X, Tiles[currentTile].Body.Position.Y), null, Color.White, Tiles[currentTile].Body.Rotation, new Vector2(TileSize.X / 2, TileSize.Y / 2), 1, SpriteEffects.None, 0f);
                    }
                    currentTile++;
                }
            }
        }

        private void DrawForegroundLayer(ref SpriteBatch spriteBatch)
        {

        }

        #endregion

        private Tile LoadTile(ref Game game, string name, TileCollision tileCollision)
        {
            return new Tile(game.Content.Load<Texture2D>(@"Textures\tiles\" + name), tileCollision);
        }

        private Tile LoadTile(ref Game game, int tilesType)
        {
            if (tilesType != 0)
            {
                try
                {
                    return LoadTile(ref game, "sand_tiles_0" + tilesType.ToString(), TileCollision.Impassable);
                }
                catch (ContentLoadException)
                {
                    throw new NotSupportedException("Tile type not found!");
                }
            }
            else
            {
                return new Tile(null, TileCollision.Passable);
            }
        }  
    }   
}
